package com.zito.health.service.impl;

import com.zito.health.api.exception.CustomException;
import com.zito.health.api.exception.UnauthorizedException;
import com.zito.health.api.result.Constants;
import com.zito.health.api.utils.JedisUtil;
import com.zito.health.entity.User;
import com.zito.health.mapper.UserMapper;
import com.zito.health.service.UserService;
import com.zito.health.vo.UserVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @description:
 * @author: gxt
 * @time: 2019/10/12 10:27
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User save(User object) {
        object.setAddtime(new Date());
        object.setEdittime(object.getAddtime());

        int res = userMapper.insertSelective(object);
        return object;
    }

    @Override
    public void delete(Integer id) {
        userMapper.deleteByPrimaryKey(id);
    }

    @Override
    public void update(User object) {
        object.setEdittime(new Date());
        userMapper.updateByPrimaryKeySelective(object);
    }

    @Override
    public List<User> query() {
        return userMapper.selectAll();
    }

    @Override
    public List<User> query(User object) {
        return userMapper.select(object);
    }

    @Override
    public User queryOne(User object) {
        return userMapper.selectOne(object);
    }

    @Override
    public User queryById(Integer id) {
        User object = userMapper.selectByPrimaryKey(id);
        return object;
    }

    @Override
    public User queryUserById(Integer id) {
        return userMapper.queryUserById(id);
    }

    @Override
    public boolean exists(Integer id) {
        return userMapper.existsWithPrimaryKey(id);
    }

    @Override
    public List<UserVo> queryList(UserVo param) {
        return userMapper.queryList(param);
    }

    @Override
    public List<User> validateUsername4Update(User u) {
        return userMapper.validateUsername4Update(u);
    }

    @Override
    public List<UserVo> list4Admin(UserVo param) {

        return userMapper.list4Admin(param);
    }

    @Override
    public HashMap<String, Object> exchangeToken(String username, String password) {
        // 数据合法性校验，不信任任何输入是省得数据库烦
        if (StringUtils.isAnyEmpty(username, password))
            throw new UnauthorizedException("需要用户名与密码(Username and password required.)");

        // 拉用户，如果不区分用户不存在和密码错，直接丢 password 进来就好
        final User user = queryOne(new User() {{
                                       setUsername(username);
                                   }}
        );

        // 用户名不存在或用户被封禁单独报错
        if (null == user || user.getEnabled() == 2)
            throw new UnauthorizedException("该帐号不存在(The account does not exist.)");

        // 按道理说这里应该做个密码校验 但是我也不知道怎么加密的 不先做了。 看到了 就写上了
        if (!verifyPassword(user, password)) throw new UnauthorizedException("帐号或密码错误");

        if (!authorityAuthentication(user)) throw new UnauthorizedException("暂时没有权限(No permission.)");

        // 要求怎么简单怎么来 UUIDv4 作为 Token，啥也不用管了 就这样吧
        String token = UUID.randomUUID().toString();

        // Redis 直写，就算出错也不是用户错
        if ("OK".equals(JedisUtil.setObject(Constants.APP_TOKEN + token, user.getUserid(), 604800))) {
            HashMap<String, Object> output = new HashMap<String, Object>();
            output.put("token", token);
            output.put("user", user);
            return output;
        } else throw new CustomException("暂时无法登录请稍候");
    }

    private boolean verifyPassword(User su, String password) {

        // 直接用 equals 做密码校验，怎么简单这么来   不会有人攻击 有只能~~ 自认倒霉
        return _generatePassword(password).equals(su.getPassword());

    }

    private String _generatePassword(String password) {

        // 密码生成，本来避免重复，应该加上用户名去验证 开始的时候 好像没怎么做 所以 就简单加个密 能用就好了
        return DigestUtils.md5Hex(password.trim());

    }

    //权限控制 简单的处理下
    private Boolean authorityAuthentication(User user) {
        Integer[] sys = {1, 2, 3, 7, 9};
        for (int i = 0; i < sys.length; i++) {
            if (user.getRoleId() == sys[i]) {
                return true;
            }
        }
        return false;
    }


}
